package com.simplehire.service;

import org.apache.pdfbox.pdmodel.PDDocument;
import org.apache.pdfbox.text.PDFTextStripper;
import org.apache.poi.xwpf.usermodel.*;
import org.openxmlformats.schemas.wordprocessingml.x2006.main.CTText;
import org.apache.tika.Tika;
import org.apache.tika.exception.TikaException;
import org.springframework.stereotype.Service;
import org.springframework.web.multipart.MultipartFile;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import java.io.IOException;
import java.io.InputStream;
import java.util.List;

@Service
public class FileProcessingService {
    
    private static final Logger logger = LoggerFactory.getLogger(FileProcessingService.class);

    private static final long MAX_FILE_SIZE = 10 * 1024 * 1024; // 10MB
    private static final String[] ALLOWED_EXTENSIONS = {".pdf", ".docx", ".doc"};

    /**
     * 从上传的文件中提取文本内容
     */
    public String extractTextFromFile(MultipartFile file) {
        if (file == null || file.isEmpty()) {
            throw new IllegalArgumentException("文件不能为空");
        }

        // 检查文件大小
        if (file.getSize() > MAX_FILE_SIZE) {
            throw new IllegalArgumentException("文件大小不能超过10MB");
        }

        String filename = file.getOriginalFilename();
        if (filename == null) {
            throw new IllegalArgumentException("无效的文件名");
        }

        String extension = getFileExtension(filename).toLowerCase();
        logger.info("开始处理文件: {}, 扩展名: {}, 文件大小: {} bytes", filename, extension, file.getSize());
        
        try {
            switch (extension) {
                case ".pdf":
                    System.out.println("开始处理PDF文件");
                    return extractTextFromPDF(file.getInputStream());
                case ".docx":
                    System.out.println("开始处理DOCX文件");
                    return extractTextFromDOCX(file.getInputStream());
                case ".doc":
                    throw new UnsupportedOperationException("暂不支持.doc格式，请使用.docx格式");
                default:
                    throw new IllegalArgumentException("不支持的文件格式: " + extension + "。支持的格式: PDF, DOCX");
            }
        } catch (IOException e) {
            System.err.println("文件处理IOException: " + e.getMessage());
            e.printStackTrace();
            throw new IllegalArgumentException("文件读取失败: " + e.getMessage(), e);
        } catch (Exception e) {
            System.err.println("文件处理时发生未知错误: " + e.getMessage());
            e.printStackTrace();
            throw new IllegalArgumentException("文件处理失败: " + e.getMessage(), e);
        }
    }

    /**
     * 从PDF文件中提取文本
     */
    private String extractTextFromPDF(InputStream inputStream) throws IOException {
        byte[] pdfBytes = inputStream.readAllBytes();
        
        try (PDDocument document = org.apache.pdfbox.Loader.loadPDF(pdfBytes)) {
            if (document.isEncrypted()) {
                throw new IllegalArgumentException("不支持加密的PDF文件");
            }

            if (document.getNumberOfPages() == 0) {
                throw new IllegalArgumentException("PDF文件为空或损坏");
            }

            PDFTextStripper stripper = new PDFTextStripper();
            stripper.setStartPage(1);
            stripper.setEndPage(document.getNumberOfPages());
            
            String text = stripper.getText(document);
            
            if (text == null || text.trim().isEmpty()) {
                throw new IllegalArgumentException("PDF文件中没有找到文本内容，可能是扫描版PDF或图片格式");
            }
            
            return cleanText(text);
        } catch (IOException e) {
            throw new IllegalArgumentException("PDF文件格式错误或损坏：" + e.getMessage());
        }
    }

    /**
     * 从DOCX文件中提取文本
     */
    private String extractTextFromDOCX(InputStream inputStream) throws IOException {
        logger.info("开始处理DOCX文件...");
        
        // 首先读取所有字节，以便后续使用Tika作为备用方案
        byte[] fileBytes = inputStream.readAllBytes();
        
        try (XWPFDocument document = new XWPFDocument(new java.io.ByteArrayInputStream(fileBytes))) {
            StringBuilder text = new StringBuilder();
            
            // 提取段落文本
            List<XWPFParagraph> paragraphs = document.getParagraphs();
            logger.info("DOCX文件包含 {} 个段落", paragraphs.size());
            
            for (int i = 0; i < paragraphs.size(); i++) {
                XWPFParagraph paragraph = paragraphs.get(i);
                StringBuilder paragraphText = new StringBuilder();
                
                // 从段落的runs中提取文本
                List<XWPFRun> runs = paragraph.getRuns();
                
                // 详细调试前10个段落
                if (i < 10) {
                    logger.info("处理段落 {} - runs数量: {}", i + 1, runs.size());
                }
                
                for (int j = 0; j < runs.size(); j++) {
                    XWPFRun run = runs.get(j);
                    
                    // 尝试多种方法获取run的文本
                    String runText = null;
                    
                    // 方法1: getText(0)
                    try {
                        runText = run.getText(0);
                    } catch (Exception e) {
                        if (i < 10) logger.debug("段落 {} run {} getText(0)失败: {}", i + 1, j + 1, e.getMessage());
                    }
                    
                    // 方法2: toString()
                    if (runText == null || runText.isEmpty()) {
                        try {
                            runText = run.toString();
                        } catch (Exception e) {
                            if (i < 10) logger.debug("段落 {} run {} toString()失败: {}", i + 1, j + 1, e.getMessage());
                        }
                    }
                    
                    // 方法3: 直接从CTR获取文本
                    if (runText == null || runText.isEmpty()) {
                        try {
                            if (run.getCTR() != null && run.getCTR().getTList() != null) {
                                for (CTText ctText : run.getCTR().getTList()) {
                                    if (ctText.getStringValue() != null) {
                                        runText = (runText == null ? "" : runText) + ctText.getStringValue();
                                    }
                                }
                            }
                        } catch (Exception e) {
                            if (i < 10) logger.debug("段落 {} run {} CTR方法失败: {}", i + 1, j + 1, e.getMessage());
                        }
                    }
                    
                    // 方法4: 尝试从run的所有文本节点获取
                    if (runText == null || runText.isEmpty()) {
                        try {
                            StringBuilder runTextBuilder = new StringBuilder();
                            if (run.getCTR() != null) {
                                // 获取所有文本节点
                                if (run.getCTR().getTArray() != null) {
                                    for (int k = 0; k < run.getCTR().getTArray().length; k++) {
                                        CTText ctText = run.getCTR().getTArray(k);
                                        if (ctText != null && ctText.getStringValue() != null) {
                                            runTextBuilder.append(ctText.getStringValue());
                                        }
                                    }
                                }
                                // 尝试获取其他文本内容
                                if (run.getCTR().getInstrTextArray() != null) {
                                    for (int k = 0; k < run.getCTR().getInstrTextArray().length; k++) {
                                        if (run.getCTR().getInstrTextArray(k) != null) {
                                            runTextBuilder.append(run.getCTR().getInstrTextArray(k).getStringValue());
                                        }
                                    }
                                }
                            }
                            if (runTextBuilder.length() > 0) {
                                runText = runTextBuilder.toString();
                            }
                        } catch (Exception e) {
                            if (i < 10) logger.debug("段落 {} run {} 方法4失败: {}", i + 1, j + 1, e.getMessage());
                        }
                    }
                    
                    // 方法5: 尝试获取run的原始XML内容
                    if (runText == null || runText.isEmpty()) {
                        try {
                            if (run.getCTR() != null) {
                                String xmlContent = run.getCTR().toString();
                                if (xmlContent != null && xmlContent.contains(">") && xmlContent.contains("<")) {
                                    // 简单的XML文本提取
                                    String[] parts = xmlContent.split(">");
                                    StringBuilder xmlTextBuilder = new StringBuilder();
                                    for (String part : parts) {
                                        if (part.contains("<")) {
                                            String textPart = part.substring(0, part.indexOf("<"));
                                            if (!textPart.trim().isEmpty() && !textPart.contains("xml") && !textPart.contains("w:")) {
                                                xmlTextBuilder.append(textPart);
                                            }
                                        }
                                    }
                                    if (xmlTextBuilder.length() > 0) {
                                        runText = xmlTextBuilder.toString();
                                    }
                                }
                            }
                        } catch (Exception e) {
                            if (i < 10) logger.debug("段落 {} run {} XML方法失败: {}", i + 1, j + 1, e.getMessage());
                        }
                    }
                    
                    if (runText != null && !runText.trim().isEmpty()) {
                        paragraphText.append(runText);
                        if (i < 10) {
                            logger.info("段落 {} run {} 成功提取文本: '{}'", i + 1, j + 1, 
                                runText.length() > 30 ? runText.substring(0, 30) + "..." : runText);
                        }
                    } else if (i < 10) {
                        logger.warn("段落 {} run {} 无法提取文本", i + 1, j + 1);
                    }
                }
                
                // 如果runs为空或没有提取到文本，尝试使用getText()方法
                if (paragraphText.length() == 0) {
                    String fallbackText = paragraph.getText();
                    if (fallbackText != null && !fallbackText.trim().isEmpty()) {
                        paragraphText.append(fallbackText);
                        if (i < 10) {
                            logger.info("段落 {} 使用fallback方法提取文本: '{}'", i + 1, 
                                fallbackText.length() > 30 ? fallbackText.substring(0, 30) + "..." : fallbackText);
                        }
                    }
                }
                
                String finalParagraphText = paragraphText.toString().trim();
                if (!finalParagraphText.isEmpty()) {
                    text.append(finalParagraphText).append("\n");
                }
                
                // 调试信息：记录每个段落的最终结果
                if (i < 10) {
                    logger.info("段落 {} 最终结果 - 文本长度: {}, 内容: '{}'", 
                        i + 1, 
                        finalParagraphText.length(),
                        finalParagraphText.length() > 50 ? finalParagraphText.substring(0, 50) + "..." : finalParagraphText);
                }
            }
            
            // 提取表格文本
            document.getTables().forEach(table -> {
                table.getRows().forEach(row -> {
                    row.getTableCells().forEach(cell -> {
                        String cellText = cell.getText();
                        if (cellText != null && !cellText.trim().isEmpty()) {
                            text.append(cellText).append(" ");
                        }
                    });
                    text.append("\n");
                });
            });
            
            // 提取页眉页脚文本
            document.getHeaderList().forEach(header -> {
                header.getParagraphs().forEach(paragraph -> {
                    String headerText = paragraph.getText();
                    if (headerText != null && !headerText.trim().isEmpty()) {
                        text.append(headerText).append("\n");
                    }
                });
            });
            
            document.getFooterList().forEach(footer -> {
                footer.getParagraphs().forEach(paragraph -> {
                    String footerText = paragraph.getText();
                    if (footerText != null && !footerText.trim().isEmpty()) {
                        text.append(footerText).append("\n");
                    }
                });
            });
            
            String result = text.toString().trim();
            logger.info("原始提取的文本长度: {}", result.length());
            logger.info("原始提取的文本预览: {}", result.length() > 100 ? result.substring(0, 100) + "..." : result);
            
            // 如果原始文本为空，尝试更深入的文本提取
            if (result.isEmpty()) {
                logger.warn("警告: 从DOCX文件中没有提取到任何文本内容，尝试深度提取...");
                logger.info("段落数量: {}", paragraphs.size());
                logger.info("表格数量: {}", document.getTables().size());
                logger.info("页眉数量: {}", document.getHeaderList().size());
                logger.info("页脚数量: {}", document.getFooterList().size());
                
                // 尝试从文档的所有body元素中提取文本
                try {
                    logger.info("文档是否为空: {}", document.getBodyElements().isEmpty());
                    logger.info("文档元素数量: {}", document.getBodyElements().size());
                    
                    // 尝试从所有body元素中提取文本
                    StringBuilder deepText = new StringBuilder();
                    for (IBodyElement element : document.getBodyElements()) {
                        if (element instanceof XWPFParagraph) {
                            XWPFParagraph para = (XWPFParagraph) element;
                            String paraText = para.getText();
                            if (paraText != null && !paraText.trim().isEmpty()) {
                                deepText.append(paraText).append("\n");
                            }
                        } else if (element instanceof XWPFTable) {
                            XWPFTable table = (XWPFTable) element;
                            for (XWPFTableRow row : table.getRows()) {
                                for (XWPFTableCell cell : row.getTableCells()) {
                                    String cellText = cell.getText();
                                    if (cellText != null && !cellText.trim().isEmpty()) {
                                        deepText.append(cellText).append(" ");
                                    }
                                }
                                deepText.append("\n");
                            }
                        }
                    }
                    
                    String deepResult = deepText.toString().trim();
                    if (!deepResult.isEmpty()) {
                        logger.info("深度提取成功，文本长度: {}", deepResult.length());
                        result = deepResult;
                    } else {
                        logger.warn("深度提取也未能获取到文本内容，尝试使用Apache Tika...");
                        
                        // 最终备用方案：使用Apache Tika
                        try {
                            Tika tika = new Tika();
                            String tikaResult = tika.parseToString(new java.io.ByteArrayInputStream(fileBytes));
                            if (tikaResult != null && !tikaResult.trim().isEmpty()) {
                                logger.info("Apache Tika提取成功，文本长度: {}", tikaResult.length());
                                logger.info("Apache Tika提取的文本预览: {}", 
                                    tikaResult.length() > 200 ? tikaResult.substring(0, 200) + "..." : tikaResult);
                                result = tikaResult.trim();
                            } else {
                                logger.warn("Apache Tika也未能提取到文本内容");
                            }
                        } catch (Exception tikaException) {
                            logger.error("Apache Tika提取失败: {}", tikaException.getMessage());
                        }
                    }
                } catch (Exception e) {
                    logger.warn("深度文本提取失败: {}", e.getMessage());
                }
            }
            
            String finalText = cleanText(result);
            logger.info("清理后的文本长度: {}", finalText.length());
            logger.info("清理后的文本预览: {}", finalText.length() > 100 ? finalText.substring(0, 100) + "..." : finalText);
            
            if (finalText.trim().isEmpty()) {
                throw new IllegalArgumentException("DOCX文件中没有找到文本内容。请确保文件包含可读取的文本，而不是仅包含图片或其他非文本元素。");
            }
            
            return finalText;
        } catch (IOException e) {
            logger.error("DOCX文件处理失败: {}", e.getMessage(), e);
            throw new IllegalArgumentException("DOCX文件格式错误或损坏：" + e.getMessage());
        } catch (Exception e) {
            logger.error("DOCX文件处理时发生未知错误: {}", e.getMessage(), e);
            throw new IllegalArgumentException("处理DOCX文件时发生错误：" + e.getMessage());
        }
    }

    /**
     * 清理和格式化文本
     */
    private String cleanText(String text) {
        if (text == null) {
            return "";
        }
        
        // 移除多余的空格和制表符，但保留换行符
        text = text.replaceAll("[ \t]+", " ");
        
        // 移除多余的换行符（3个或以上连续换行符替换为2个）
        text = text.replaceAll("\n{3,}", "\n\n");
        
        // 移除首尾空白
        text = text.trim();
        
        return text;
    }

    /**
     * 获取文件扩展名
     */
    private String getFileExtension(String filename) {
        int lastDotIndex = filename.lastIndexOf('.');
        if (lastDotIndex == -1) {
            return "";
        }
        return filename.substring(lastDotIndex);
    }

    /**
     * 验证文件类型
     */
    public boolean isValidFileType(String filename) {
        if (filename == null) {
            return false;
        }
        
        String extension = getFileExtension(filename).toLowerCase();
        for (String allowedExt : ALLOWED_EXTENSIONS) {
            if (allowedExt.equals(extension)) {
                return true;
            }
        }
        return false;
    }

    /**
     * 验证文件大小
     */
    public boolean isValidFileSize(long fileSize) {
        return fileSize > 0 && fileSize <= MAX_FILE_SIZE;
    }

    /**
     * 获取支持的文件类型描述
     */
    public String getSupportedFileTypes() {
        return String.join(", ", ALLOWED_EXTENSIONS);
    }

    /**
     * 获取最大文件大小（MB）
     */
    public long getMaxFileSizeMB() {
        return MAX_FILE_SIZE / (1024 * 1024);
    }
}